package com.ruoyi.common.config;


import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

@Slf4j
@EnableConfigurationProperties(MinioProperties.class)
@Import(MinioConfig.class)
@Component
public class MinioTemplate {

    private final static String separator = "/";
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinioProperties prop;

    /**
     * 构建文件存储目录
     *
     * @param
     * @param filename yyyy/mm/dd/file.jpg
     * @return
     */
    public String buildFilePath(String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        String date = DateTime.now().toString("/yyyyMMdd/");
        String concat = IdWorker.get32UUID().concat(filename.substring(filename.lastIndexOf(".")));
        stringBuilder.append(date).append(concat);
        return stringBuilder.toString();
    }

    /**
     * 上传图片文件
     * <p>
     * 目录名 可以为空
     *
     * @param filename    文件名
     * @param inputStream 文件流
     * @param bucketName  桶名稱
     * @return 文件全路径
     */
    public String uploadFile(String filename, InputStream inputStream, String bucketName) {
        if (StringUtils.isBlank(bucketName)) {
            bucketName = prop.getBucket();
        }
        String filePath = buildFilePath(filename);
        try {
            // 1.存储桶是否存在
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (found) {
                System.out.println(bucketName + " exists");
            } else {
                System.out.println(bucketName + " does not exist");
            }
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                System.out.println(bucketName + " is created successfully");
            }
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .bucket(bucketName)
                    .stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(prop.getReadPath());
            urlPath.append("/" + bucketName).append(filePath);
            return urlPath.toString();
        } catch (Exception ex) {
            log.error("minio put file error.", ex);
            throw new RuntimeException("上传文件失败");
        }
    }

    public String uploadFile(String filename, MultipartFile file, String bucketName) {
        if (StringUtils.isBlank(bucketName)) {
            bucketName = prop.getBucket();
        }
        String filePath = buildFilePath(filename);
        try {
            // 1.存储桶是否存在
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (found) {
                System.out.println(bucketName + " exists");
            } else {
                System.out.println(bucketName + " does not exist");
            }
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                System.out.println(bucketName + " is created successfully");
            }
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .bucket(bucketName)
                    .stream(file.getInputStream(), file.getInputStream().available(), -1)
                    .contentType(file.getContentType())
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(prop.getReadPath());
            urlPath.append("/" + bucketName).append(filePath);
            return urlPath.toString();
        } catch (Exception ex) {
            log.error("minio put file error.", ex);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 上传html文件
     * <p>
     * 文件前缀
     *
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    public String uploadHtmlFile(String filename, InputStream inputStream) {
        String filePath = "/html/" + filename;
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("text/html")
                    .bucket(prop.getBucket()).stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(prop.getReadPath());
            urlPath.append(separator + prop.getBucket());
            urlPath.append(separator).append(filePath);
            return urlPath.toString();
        } catch (Exception ex) {
            log.error("minio put file error.", ex);
            ex.printStackTrace();
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     *
     * @param fileUrl 文件全路径
     */
    public void delete(String fileUrl) {
        String key = fileUrl.replace(prop.getEndpoint() + "/", "");
        int index = key.indexOf(separator);
        String bucket = StringUtils.substringBefore(key, separator);
        String filePath = StringUtils.substringAfter(key, separator);
        // 删除Objects
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
        try {
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            log.error("minio remove file error.  pathUrl:{}", fileUrl);
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     *
     * @param pathUrl 文件全路径
     * @return 文件流
     */
    public byte[] downLoadFile(String pathUrl) {
        String key = pathUrl.replace(prop.getEndpoint() + "/", "");
        int index = key.indexOf(separator);
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(prop.getBucket()).object(filePath).build());
        } catch (Exception e) {
            log.error("minio down file error.  pathUrl:{}", pathUrl);
            e.printStackTrace();
        }

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while (true) {
            try {
                if (!((rc = inputStream.read(buff, 0, 100)) > 0)) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            byteArrayOutputStream.write(buff, 0, rc);
        }
        return byteArrayOutputStream.toByteArray();
    }
}
